package logic

import (
	"errors"
	"fmt"
	"game/src/pb"
	"github.com/golang/protobuf/proto"
	"io"
	"os"
	"sync"
)

/**
这个类代表数据库的相关操作
*/

type DataStore struct {
	allRoleDataKeyName map[string]*RoleData
	roleLock           sync.RWMutex //读写连接的读写锁

	allAllianceDataKeyName map[string]*AllianceData
	allianceLock           sync.RWMutex //读写连接的读写锁
}

var Ds *DataStore

func NewDataStore() *DataStore {
	return &DataStore{
		allRoleDataKeyName:     make(map[string]*RoleData),
		allAllianceDataKeyName: make(map[string]*AllianceData),
	}
}

func (ds *DataStore) GetRoleByName(name string) (*RoleData, error) {
	ds.roleLock.RLock()
	defer ds.roleLock.RUnlock()
	if rd, ok := ds.allRoleDataKeyName[name]; ok {
		return rd, nil
	}
	return nil, errors.New("角色未找到")
}

func (ds *DataStore) SaveRole(data *RoleData) {
	ds.roleLock.Lock()
	defer ds.roleLock.Unlock()
	ds.allRoleDataKeyName[data.Name] = data
}

func (ds *DataStore) GetAllianceByName(name string) *AllianceData {
	ds.allianceLock.RLock()
	defer ds.allianceLock.RUnlock()

	if rd, ok := ds.allAllianceDataKeyName[name]; ok {
		return rd
	}
	//fmt.Println("工会未找到，name=", name)
	return nil
}

func (ds *DataStore) GetAllianceByList() (ret map[string]AllianceData) {
	ds.allianceLock.RLock()
	defer ds.allianceLock.RUnlock()
	ret = make(map[string]AllianceData)
	for s, k := range ds.allAllianceDataKeyName {
		if k != nil {
			ret[s] = *k
		}
	}
	return
}

func (ds *DataStore) SaveAlliance(data *AllianceData) {
	ds.allianceLock.Lock()
	defer ds.allianceLock.Unlock()
	ds.allAllianceDataKeyName[data.AllianceName] = data
}

func (ds *DataStore) RemoveAlliance(allianceName string) {
	ds.allianceLock.Lock()
	defer ds.allianceLock.Unlock()

	delete(ds.allAllianceDataKeyName, allianceName)
}

func Save() {
	// TODO  定期保存到库，
}

// ItemConfig 此处代表道具配置，用来检测道具是否存在，对应游戏里的配置类，并不合理
var ItemConfig map[int32]Item

// AllianceItemInItPro 公会初始化的数据，数据暂时存这里好了，并不合理
var AllianceItemInItPro map[int32]int32

func InitItemPro() {
	if ItemConfig == nil {
		ItemConfig = make(map[int32]Item, 10)
		items := ReadItems().Items
		AllianceItemInItPro = make(map[int32]int32, 10)
		for i := range items {
			it := items[i]
			_, ok := ItemConfig[it.Id]
			if !ok {
				ItemConfig[it.Id] = Item{
					Id:   it.Id,
					Type: it.ItemType,
					Name: it.Name,
				}
			}
			num, ok := AllianceItemInItPro[it.Id]
			if ok {
				AllianceItemInItPro[it.Id] = num + it.Number
			} else {
				AllianceItemInItPro[it.Id] = it.Number
			}
		}
	}
}

func ReadItems() (arr *pb.TestItem_Array) {
	filename := "data/testItem.data"
	file, _ := os.Open(filename) //打开文件

	defer file.Close() //关闭文件 ,defer 会在程序最后运行
	fs, _ := file.Stat()
	buffer := make([]byte, fs.Size()) //创建 byte切片
	//把file文件内容读取到buffer
	io.ReadFull(file, buffer)

	//初始化pb结构体对象并将buffer中的文件内容读取到pb结构体中
	msg := &pb.TestItem_Array{}
	proto.Unmarshal(buffer, msg) //反序列化数据
	return msg
}

func ProtoBuffWrite() {
	//初始化protobuf数据格式
	msg := &pb.TestItem{
		Id:       *proto.Int32(99),
		Name:     *proto.String("测试道具"),
		ItemType: *proto.Int32(99),
		Number:   *proto.Int32(99),
	}
	filename := "d:/myTest.txt"
	fmt.Printf("使用protobuf创建文件 %s\n", filename)
	fObj, _ := os.Create(filename)  //创建文件
	defer fObj.Close()              //关闭文件 ,defer 会在程序最后运行
	buffer, _ := proto.Marshal(msg) //序列化数据
	fObj.Write(buffer)              //写入文件
}
